import { BeforeOpenModalResult, ElementPropertyConfig, PropertyChangeObject } from '@farris/ide-property-panel';
import { Injectable, Injector } from '@angular/core';
import { ControlService } from '../../../../../../service/control.service';
import { IdService } from '@farris/ui-common';
import { NotifyService } from '@farris/ui-notify';
import { EventEditorService, DomService, FormBasicService, WebCmdService, UniformEditorDataUtil } from '@farris/designer-services';
import { CodeEditorComponent, CollectionWithPropertyConverter, CollectionWithPropertyEditorComponent, IconSelectEditorComponent } from '@farris/designer-devkit';
import { ImportCmpComponent, ImportCmpConverter } from '@farris/designer-devkit';
import { SelectMappingComponent, MappingConverter } from '@farris/designer-devkit';
import { DgControl } from '../../../../../../utils/dg-control';
import { EventsEditorFuncUtils } from '../../../../../../utils/events-editor-func';

export class ToolBarMoreProp {

    needOpenHelpMap = new Map<string, any>();

    private controlService: ControlService;
    private domService: DomService;
    private idService: IdService;
    private notifyService: NotifyService;
    public formBasicService: FormBasicService;
    public eventEditorService: EventEditorService;
    //事件编辑器集成
    public webCmdService: WebCmdService;

    constructor(private injector: Injector) {

        this.controlService = this.injector.get(ControlService);
        this.domService = this.injector.get(DomService);
        this.eventEditorService = this.injector.get(EventEditorService);
        this.formBasicService = this.injector.get(FormBasicService);
        this.webCmdService = this.injector.get(WebCmdService);
        this.idService = this.injector.get(IdService);
        this.notifyService = this.injector.get(NotifyService);
    }

    /**
     * toolbarItem 属性配置
     * @param viewModelId 按钮所在视图模型ID
     * @param disableChildItem 是否禁用子级按钮
     * @param selectedNode 当前选中行数据
     */
    public getPropertyConfig(viewModelId: string, propertyData: any, disableChildItem = true)
        : ElementPropertyConfig[] {
        // public getPropertyConfig(viewModelId: string, disableChildItem: boolean, propertyData: any, isFirstLevel: boolean)
        //     : ElementPropertyConfig[] {

        const propertyConfig: ElementPropertyConfig[] = [];

        // 基本信息属性
        const basicPropConfig = this.getBasicPropConfig();
        propertyConfig.push(basicPropConfig);

        // 弹出表单框属性(目前未验证)
        const openModalPropConfigs = this.getOpenModalPropConfigs(propertyData, viewModelId);

        // 外观属性
        const appearancePropConfig = this.getAppearanceItemPropConfig(propertyData, viewModelId, disableChildItem,
            openModalPropConfigs, true);
        propertyConfig.push(appearancePropConfig);
        // 行为属性
        const behaviorPropConfig = this.getBehaviorItemPropConfig(propertyData, viewModelId, openModalPropConfigs);
        propertyConfig.push(behaviorPropConfig);
        propertyConfig.push(...openModalPropConfigs);

        // 事件属性
        const eventPropConfig = this.getEventPropertyConfig(propertyData, viewModelId);
        propertyConfig.push(eventPropConfig);

        return propertyConfig;
    }
    private getBasicPropConfig(): ElementPropertyConfig {

        return {
            categoryId: 'basic',
            categoryName: '基本信息',
            properties: [
                {
                    propertyID: 'id',
                    propertyName: '标识',
                    propertyType: 'string',
                    description: '工具栏按钮的标识'
                },
                {
                    propertyID: 'text',
                    propertyName: '标签',
                    propertyType: 'string',
                    description: '工具栏按钮的标签',
                    readonly: false
                }
            ]
        };
    }

    private getAppearanceItemPropConfig(
        propertyData: any, viewModelId: string, disableChildItem: boolean, openModalPropConfigs: ElementPropertyConfig[],
        isFirstLevel: boolean): ElementPropertyConfig {

        return {
            categoryId: 'appearance',
            categoryName: '外观',
            properties: [
                {
                    propertyID: 'appearance',
                    propertyName: '样式',
                    propertyType: 'cascade',
                    cascadeConfig: [
                        {
                            propertyID: 'class',
                            propertyName: '按钮样式',
                            propertyType: 'string',
                            description: '工具栏按钮样式'
                        },
                        {
                            propertyID: 'dropdownCls',
                            propertyName: '下拉框样式',
                            propertyType: 'string',
                            description: '工具栏按钮下拉框样式',
                            visible: !disableChildItem
                        }
                    ]
                },
                {
                    propertyID: 'split',
                    propertyName: '下拉按钮分离',
                    propertyType: 'boolean',
                    defaultValue: false,
                    description: '工具栏按下拉按钮是否分离',
                    visible: !disableChildItem
                },
                {
                    propertyID: 'icon',
                    propertyName: '图标',
                    propertyType: 'modal',
                    description: '图标设置',
                    editor: IconSelectEditorComponent,
                    editorParams: { needIconClass: true },
                    visible: isFirstLevel
                },
                {
                    propertyID: 'tipsEnable',
                    propertyName: '启用提示',
                    propertyType: 'boolean',
                    description: '是否启用提示信息',
                    defaultValue: false
                },
                {
                    propertyID: 'tipsText',
                    propertyName: '提示消息内容',
                    propertyType: 'modal',
                    description: '提示消息内容设置',
                    editor: CodeEditorComponent,
                    editorParams: {
                        language: 'html'
                    },
                    visible: propertyData.tipsEnable
                }
            ],
            setPropertyRelates(changeObject: PropertyChangeObject, data, parameters) {
                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'tipsEnable': {
                        const tipsText = this.properties.find(p => p.propertyID === 'tipsText');
                        if (tipsText) {
                            tipsText.visible = changeObject.propertyValue;
                        }
                    }
                }
            }
        };
    }

    private getBehaviorItemPropConfig(
        propertyData: any, viewModelId: string, openModalPropConfigs: ElementPropertyConfig[]): ElementPropertyConfig {

        const self = this;
        return {
            categoryId: 'behavior',
            categoryName: '行为',
            properties: [
                {
                    propertyID: 'visible',
                    propertyName: '是否可见',
                    propertyType: 'unity',
                    description: '运行时组件是否可见',
                    editorParams: {
                        controlName: UniformEditorDataUtil.getControlName(propertyData),
                        constType: 'enum',
                        editorOptions: {
                            types: ['const', 'variable'],
                            enums: [{ key: true, value: '是' }, { key: false, value: '否' }],
                            variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                            getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                            newVariableType: 'Boolean',
                            newVariablePrefix: 'is'
                        }
                    }
                },
                {
                    propertyID: 'disable',
                    propertyName: '禁用',
                    propertyType: 'editableSelect',
                    description: '是否禁用',
                    iterator: [{ key: true, value: 'true' }, { key: false, value: 'false' }]
                },
                // 暂不放开使用模式，需要验证在弹出窗口里的使用模式属性
                // {
                //     propertyID: 'usageMode',
                //     propertyName: '使用模式',
                //     propertyType: 'select',
                //     iterator: [{ key: 'button', value: '按钮' }, { key: 'open-modal', value: '弹出表单' }, { key: 'open-help', value: '弹出帮助' }],
                //     refreshPanelAfterChanged: true
                // }
            ],
            setPropertyRelates(changeObject: PropertyChangeObject, data, parameters) {
                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'usageMode': {
                        if (openModalPropConfigs && openModalPropConfigs.length) {
                            openModalPropConfigs.forEach(config => {
                                config.hide = propertyData.usageMode !== 'open-modal';
                            });
                        }
                        if (changeObject.propertyValue === 'open-help') {
                            self.needOpenHelpMap.set(propertyData.id, propertyData);
                        } else {
                            self.needOpenHelpMap.delete(propertyData.id);
                        }
                        break;
                    }
                }
            }
        };
    }


    private getEventPropertyConfig(propertyData, viewModelId: string): ElementPropertyConfig {
        const self = this;
        const domService = this.domService;
        const webCmdService = this.webCmdService;
        const formBasicService = this.formBasicService;
        const eventEditorService = this.eventEditorService;
        let eventList = [
            {
                label: 'click',
                name: '点击事件'
            },
        ];
        return {
            categoryId: 'eventsEditor',
            categoryName: '事件',
            hideTitle: true,
            properties: EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, eventList),
            tabId: 'commands',
            tabName: '交互',
            setPropertyRelates(changeObject, data, parameters) {
                delete propertyData[viewModelId];
                EventsEditorFuncUtils.saveRelatedParameters(eventEditorService, domService, webCmdService, propertyData, viewModelId, eventList, parameters);
                this.properties = EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, eventList);
            }
        };
    }


    private getOpenModalPropConfigs(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig[] {
        const self = this;
        const domServ = new DomService();
        return [{
            categoryId: 'openModal',
            categoryName: '表单配置',
            hide: propertyData.usageMode !== 'open-modal',
            propertyData: propertyData.modalConfig,
            enableCascade: true,
            parentPropertyID: showPosition === 'gridFieldEditor' ? 'editor.modalConfig' : 'modalConfig',
            properties: [
                {
                    propertyID: 'modalCmp',
                    propertyName: '弹出表单',
                    propertyType: 'modal',
                    editor: ImportCmpComponent,
                    converter: new ImportCmpConverter(),
                    editorParams: { containerType: DgControl.ModalContainer.type, containerId: propertyData.id, relativePath: this.formBasicService.formMetaBasicInfo.relativePath, name: this.formBasicService.formMetaBasicInfo.name },
                    showClearButton: true,
                    afterClickClearButton(oldValue: string) {
                        domServ.deleteExternalComponent(oldValue); // 清空外部组件的声明节点
                    }
                },
                {
                    propertyID: 'mapFields',
                    propertyName: '字段映射',
                    propertyType: 'modal',
                    editor: SelectMappingComponent,
                    editorParams: {
                        sourceMetadataId: propertyData.formId,
                        viewModelId,
                        binding: {
                            type: 'Form'
                        },
                        sourceMetadataType: 'form',
                        sourceMetadataName: '弹出表单'
                    },
                    converter: new MappingConverter(),
                    beforeOpenModal(): BeforeOpenModalResult {
                        if (!propertyData.modalConfig || !propertyData.modalConfig.formId) {
                            return { result: false, message: '请先选择弹出表单！' };
                        }
                        // 取弹出表单和绑定的最新值
                        this.editorParams.helpId = propertyData.modalConfig.formId;
                        return { result: true, message: '' };
                    }
                }

            ],
            setPropertyRelates(changeObject, propData, parameters) {
                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'modalCmp': {
                        propData.component = parameters ? parameters.component : '';
                        propData.formId = parameters ? parameters.uri : '';
                        propData.mapFields = '';
                        break;
                    }
                }
            }
        },
        {
            categoryId: 'modalConfig',
            categoryName: '弹出窗口配置',
            hide: propertyData.usageMode !== 'open-modal',
            propertyData: propertyData.modalConfig,
            enableCascade: true,
            parentPropertyID: showPosition === 'gridFieldEditor' ? 'editor.modalConfig' : 'modalConfig',
            properties: [
                {
                    propertyID: 'showHeader',
                    propertyName: '显示标题栏',
                    propertyType: 'boolean'
                },
                {
                    propertyID: 'title',
                    propertyName: '标题',
                    propertyType: 'string',
                    visible: propertyData.modalConfig && propertyData.modalConfig.showHeader,
                    category: 'header'
                },
                {
                    propertyID: 'showCloseButton',
                    propertyName: '显示关闭按钮',
                    propertyType: 'boolean',
                    visible: propertyData.modalConfig && propertyData.modalConfig.showHeader,
                    category: 'header'
                },
                {
                    propertyID: 'showMaxButton',
                    propertyName: '显示最大化按钮',
                    propertyType: 'boolean',
                    visible: propertyData.modalConfig && propertyData.modalConfig.showHeader,
                    category: 'header'
                },
                {
                    propertyID: 'width',
                    propertyName: '宽度',
                    propertyType: 'number',
                    min: 0
                },
                {
                    propertyID: 'height',
                    propertyName: '高度',
                    propertyType: 'number',
                    min: 0
                },
                {
                    propertyID: 'showFooterButtons',
                    propertyName: '显示底部按钮区',
                    propertyType: 'boolean'
                },
                {
                    propertyID: 'footerButtons',
                    propertyName: '按钮组',
                    propertyType: 'modal',
                    visible: propertyData.modalConfig && propertyData.modalConfig.showFooterButtons,
                    editor: CollectionWithPropertyEditorComponent,
                    converter: new CollectionWithPropertyConverter(),
                    editorParams: {
                        modalTitle: '工具栏编辑器',
                        viewModelId,
                        idKey: 'id',
                        textKey: 'text',
                        maxCascadeLevel: 1,
                        controlType: DgControl.ToolBarItem.type,
                        defaultControlValue: {
                            id: 'toolbarItem',
                            text: '按钮',
                            appearance: {
                                class: 'btn'
                            }
                        },
                        getPropertyConfig: (selectedNode) => this.getPropertyConfig(viewModelId, false, selectedNode),
                        beforeSave: () => this.beforeToolbarSaved(propertyData.parent && propertyData.parent.id, viewModelId)
                    }
                }

            ],
            setPropertyRelates(changeObject, data, parameters) {
                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'showHeader': {
                        this.properties.map(p => {
                            if (p.category === 'header') {
                                p.visible = changeObject.propertyValue;
                            }
                        });

                        break;
                    }
                    case 'showFooterButtons': {
                        const footerButtons = this.properties.find(p => p.propertyID === 'footerButtons');
                        if (footerButtons) {
                            footerButtons.visible = changeObject.propertyValue;
                        }
                    }
                }
            }
        }];
    }



    /**
     * 按钮使用模式切换为弹出帮助
     */
    public handleOpenHelpMode(propertyData: any, parentNodeId: string, viewModelId: string) {
        if (!parentNodeId) {
            return;
        }
        const parentContainer = this.domService.domDgMap.get(parentNodeId);
        const hiddenContainerId = propertyData.id + '-hidden-container';

        // 1、增加隐藏区域，并默认创建一个帮助控件
        if (parentContainer.contents.find(c => c.id === hiddenContainerId)) {
            return;
        }
        const helpControlId = propertyData.id + '-lookup-edit';
        const hiddenContainerMetadata = this.controlService.getControlMetaData(DgControl.HiddenContainer.type);
        const helpMetadata = this.controlService.getControlMetaData(DgControl.LookupEdit.type);
        helpMetadata.id = helpControlId;
        helpMetadata.title = (propertyData.text || '') + '弹出帮助';

        Object.assign(hiddenContainerMetadata, {
            id: hiddenContainerId,
            contents: [helpMetadata]
        });

        parentContainer.contents.push(hiddenContainerMetadata);


        // 2、按钮默认绑定弹出帮助事件
        this.addOpenHiddenHelpCommand(propertyData, helpControlId, viewModelId);

        this.notifyService.success('隐藏帮助控件创建成功，控件ID：' + helpControlId);

    }

    private addOpenHiddenHelpCommand(propertyData: any, helpControlId: string, viewModelId: string) {
        // 1、配置构件
        const webcmds = this.domService.getWebCmds();
        if (!webcmds) {
            return;
        }
        const batchCmdId = '43f68561-eae4-4495-b318-d629615523f8';
        const openHiddenHelpCmdId = this.idService.generate();
        const openHiddenHelpCmdCode = propertyData.id.replace(/-/g, '').replace(/_/g, '') + 'openHiddenHelp';

        const batchCmd = webcmds.find(c => c.id === batchCmdId);
        if (!batchCmd) {
            webcmds.push({
                id: batchCmdId,
                path: 'igix/Web/WebCmp/bo-webcmp/metadata/webcmd/data-commands',
                name: 'BatchEditCommands.webcmd',
                refedHandlers: [
                    {
                        host: openHiddenHelpCmdId,
                        handler: 'openHiddenHelp'
                    }
                ]
            });
        } else {
            batchCmd.refedHandlers.push(
                {
                    host: openHiddenHelpCmdId,
                    handler: 'openHiddenHelp'
                }
            );
        }

        // 2、配置命令
        const vm = this.domService.getViewModelById(viewModelId);
        if (!vm.commands) {
            vm.commands = [];
        }
        vm.commands.push(
            {
                id: openHiddenHelpCmdId,
                code: openHiddenHelpCmdCode,
                name: (propertyData.text || '') + '打开隐藏帮助',
                params: [
                    {
                        name: 'helpId',
                        shownName: '帮助Id',
                        value: helpControlId,
                        description: '帮助Id'
                    }
                ],
                handlerName: 'openHiddenHelp',
                cmpId: batchCmdId,
                shortcut: {},
                extensions: []
            }
        );

        // 3、按钮点击事件绑定打开帮助的命令
        propertyData.click = openHiddenHelpCmdCode;


        // 涉及到新增控制器，所以这里需要获取控制器信息，方便交互面板展示命令数据
        this.webCmdService.checkCommands();

    }


    /**
     * 使用模式切换为弹出帮助的按钮，需要创建隐藏区域
     * @param parentNodeId 按钮的父级容器id
     * @param viewModelId 视图模型id
     */
    beforeToolbarSaved(parentNodeId: string, viewModelId: string) {

        if (parentNodeId && this.needOpenHelpMap.size > 0) {
            this.needOpenHelpMap.forEach(itemPropertyData => {
                this.handleOpenHelpMode(itemPropertyData, parentNodeId, viewModelId);
            });

        }
    }

}

